
# 序列化
from demo import serializers
from demo import models
from rest_framework.generics import GenericAPIView
from rest_framework import status
from rest_framework.response import Response
from rest_framework.generics import ListAPIView, CreateAPIView, UpdateAPIView, DestroyAPIView, RetrieveAPIView
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, \
    DestroyModelMixin
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView


"""
我们返现，APIView 在不同 http metho中都要重复写"查询集"和"序列化类"，为了简化，Genericview 继承了 APIView，又增加了：
1 提供的关于序列化器使用的属性与方法
属性
serializer_class 指定序列化器类
方法
1 get_serializer_class(self)            返回序列化器类
2 get_serializer(self, args, *kwargs)   返回序列化器对象，主要用来提供给Mixin扩展类使用


2 提供的关于数据库查询的属性与方法
属性
queryset 指定查询集
方法
1 get_queryset(self)    返回视图使用的查询集
2 get_object(self)      返回详情视图所需的模型类数据对象，主要用来提供给Mixin扩展类使用。

还有
pagination_class 指明分页控制类
filter_backends 指明过滤控制后端
"""
class BookListGenericAPIView(GenericAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()

    def get(self, request):
        # 获得查询集
        req = self.get_queryset()

        # 获得序列化器对象，将查询集传递进去
        s = self.get_serializer(req, many=True)

        return Response(s.data)

    def post(self, request):
        pass

class BookDetailGenericAPIView(GenericAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()

    def get(self, request, pk):
        """
        这里分析下越代码

        class GenericAPIView(views.APIView):
            lookup_field = 'pk'
            lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
            filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
            def get_object(self):
                queryset = self.filter_queryset(self.get_queryset())
                obj = get_object_or_404(queryset, **filter_kwargs)
                return obj

        def get_object_or_404(queryset, *filter_args, **filter_kwargs):
            try:
                return _get_object_or_404(queryset, *filter_args, **filter_kwargs)
            except (TypeError, ValueError, ValidationError):
                raise Http404

        得到的是模型对象
        """
        #
        req = self.get_object()

        s = self.get_serializer(req)
        return Response(s.data)

    def put(self, request, pk):

        book = self.get_object()

        req = request.data

        s = self.get_serializer(instance=book, data=req)
        s.is_valid(raise_exception=True)
        s.save()
        return Response(s.data, status=status.HTTP_200_OK)

"""
Genericview可以和其他几个同级类实现多继承：
1 ListModelMixin 列表视图扩展类，提供list(request, *args, **kwargs)方法快速实现列表视图，返回200状态码。
2 CreateModelMixin 创建视图扩展类，提供create(request, *args, **kwargs)方法快速实现创建资源的视图，成功返回201状态码。
3 RetrieveModelMixin 详情视图扩展类，提供retrieve(request, *args, **kwargs)方法，可以快速实现返回一个存在的数据对象。
4 UpdateModelMixin 更新视图扩展类，提供update(request, *args, **kwargs)方法，可以快速实现更新一个存在的数据对象。
5 DestroyModelMixin 删除视图扩展类，提供destroy(request, *args, **kwargs)方法，可以快速实现删除一个存在的数据对象。
"""
class BookListMixinView(ListModelMixin, CreateModelMixin, GenericAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)

class BookDetailMixinView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()

    def get(self, request, pk):
        return self.retrieve(request, pk)

    def put(self, request, pk):
        return self.update(request, pk)

    def delete(self, request, pk):
        return self.destroy(request, pk)

"""
还能够更精简，DRF针对HTTP的不同方法，也做了相应的视图集，这些其实
1 ListAPIView：其实是(mixins.ListModelMixin,GenericAPIView)
2 CreateAPIView：同理
3 RetrieveAPIView：同理
4 UpdateAPIView：同理
5 DestroyAPIView：同理
"""
class BookListGetAPIView(ListAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()


class BookListCreateAPIView(CreateAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()


class BookDetailRetrieveAPIView(RetrieveAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()


class BookDetailUpdateAPIView(UpdateAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()


class BookDetailDeleteAPIView(DestroyAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()


"""
list和create可以合并为ListCreateAPIView
Retrieve，update和destroy可以合并RetrieveUpdateDestroyAPIView
"""
# 列表视图
class BookListListCreateView(ListCreateAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()

# 详情视图
class BookDetailRetrieveUpdateDestroyView(RetrieveUpdateDestroyAPIView):
    # 指定序列化器类
    serializer_class = serializers.DrfBookSerializer
    # 指定查询集
    queryset = models.Book.objects.all()